package com.example.config;
import com.example.service.authService.UserAuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.concurrent.TimeUnit;

/**
 * 认证服务端配置.
 * @Author xcg
 * @Version 1.0
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Resource
    AuthenticationManager authenticationManager;


    @Autowired
    public DataSource dataSource;




    @Bean
    public ClientDetailsService clientDetails() {
        JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
        // 使用哪一种加密方式
        clientDetailsService.setPasswordEncoder(passwordEncoder());
        return clientDetailsService;
    }


    @Autowired
    UserAuthService userAuthService;

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }



    @Override
    public void configure(ClientDetailsServiceConfigurer clientDetailsServiceConfigurer) throws Exception {
        // 内存存储配置信息+密码模式
//        serviceConfig(0, clientDetailsServiceConfigurer, dataSource, "password");
//        serviceConfig(0, clientDetailsServiceConfigurer, null, "password");
        clientDetailsServiceConfigurer.withClientDetails(clientDetails());// 使用jdbc存储

    }
//    private void serviceConfig(int flag, ClientDetailsServiceConfigurer clientDetailsServiceConfigurer, DataSource dataSource, String grantType) throws Exception {
////        if (flag == 1) {
////            clientDetailsServiceConfigurer.jdbc(dataSource);
////        } else {
//        clientDetailsServiceConfigurer
//                //存储到内存中
//                .inMemory()
//                //配置client_id
//                .withClient("client")
//                //配置client-secret
//                .secret(new BCryptPasswordEncoder().encode("123456"))
//                //配置访问token的有效期
//                .accessTokenValiditySeconds(3600)
//                //配置刷新token的有效期
//                .refreshTokenValiditySeconds(864000)
//                //配置redirect_uri，用于授权成功后跳转
////                .redirectUris("http://www.baidu.com")
//                //配置申请的权限范围
//                .scopes("all")
//                //配置grant_type，表示授权类型
//                .authorizedGrantTypes("password","refresh_token");
////        }
//    }
//

    @Bean
    public TokenStore tokenStore() {
//        InMemoryTokenStore inMemoryTokenStore = new InMemoryTokenStore();
//        return inMemoryTokenStore;
        JdbcTokenStore jdbcTokenStore = new JdbcTokenStore(dataSource);
        return jdbcTokenStore;
    }


//    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
        endpoints.tokenStore(tokenStore());// 配置令牌存储为数据库存储
        endpoints.userDetailsService(userAuthService);
        // 配置 tokenServices 参数
        DefaultTokenServices tokenServices = new DefaultTokenServices();//修改默认令牌生成服务
        tokenServices.setTokenStore(endpoints.getTokenStore());// 基于数据库令牌生成
        tokenServices.setSupportRefreshToken(true);//是否支持刷新令牌
        tokenServices.setReuseRefreshToken(false); // 是否重复使用刷新令牌( 直到过期)

        tokenServices.setClientDetailsService(endpoints.getClientDetailsService());//设置客户端信息
        tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());//用来控制令牌存储增强策略
        // 访问令牌的默认有效期( 以秒为单位)。过期的令牌为零或负数。
        tokenServices.setAccessTokenValiditySeconds((int) TimeUnit.HOURS.toSeconds(1)); // 30

        endpoints.tokenServices(tokenServices);// 使用配置令牌服务

    }



    @Override
    public void configure(AuthorizationServerSecurityConfigurer serverSecurityConfig) throws Exception {
        //允许表单认证
        serverSecurityConfig.allowFormAuthenticationForClients();
        //添加tokan校验失败返回消息
        serverSecurityConfig.authenticationEntryPoint(new AuthExceptionEntryPoint());
    }
}
